package com.hangwei.aicabinet.manager;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;

import com.hangwei.aicabinet.App;
import com.hangwei.aicabinet.model.entry.AdminCloseAllDoor;
import com.hangwei.aicabinet.model.entry.AdminOpenSuccess;
import com.hangwei.aicabinet.model.entry.CloseAllDoor;
import com.hangwei.aicabinet.model.entry.LockOpenEvent;
import com.hangwei.aicabinet.util.ByteUtil;
import com.hangwei.aicabinet.util.InstructionsUtil;
import com.hangwei.aicabinet.util.LogUtil;
import com.hangwei.aicabinet.util.SPKey;
import com.hangwei.aicabinet.util.SPUtil;
import com.hangwei.aicabinet.util.ToastUtil;

import org.greenrobot.eventbus.EventBus;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android_serialport_api.SerialPort;

import static com.hangwei.aicabinet.manager.SerialPortManager.NoResponseError;

/**
 * Created by 张龙臣 on 2018/9/16.
 * <p>
 * 写状态 主动操作
 * 01 10 00 14 00 08 10 00 01 00 01 00 01 00 01 00 01 00 01 00 01 00 01 5D 37
 * 01 10 00 14 00 08 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 2A DA
 * <p>
 * 0110 0014 0008 81CB  开锁
 * 01100014000141CD
 * 01           10        0014         0008            81CB     关
 * 设备地址    功能码    寄存器首地址  寄存器个数      校验码
 * <p>
 * <p>
 * <p>
 * 0103 0000 0008  440C
 * 读状态
 * 01 03 10           00000000000000000000000000000000  E459
 * 16个字节     读取上次写到寄存器的内容
 * <p>
 * 0-8监听锁反馈
 * <p>
 * 10-17控制寄存器通断
 * <p>
 * <p>
 * 0000 锁打开
 * 0001 锁关闭
 * <p>
 * 1.没有校验码生规则，但是返回数据长度（42）是固定的，可根据此校验
 */

public class LockManager {
    private static final int baudrate = 9600;//波特率（可自行设定）
    private static final String device = "/dev/ttyS1";
    private static SerialPort mSerialPort;
    private static InputStream mInputStream;
    private static OutputStream mOutputStream;
    private static Thread mReceiveThread;
    private static Thread mSendThread;
    private volatile static String orderOfLock;

    private static int tempWhich;

    private static StringBuilder stringBuilder;
    private static SerialPortManager.ReturnHandleCallBack mReturnHandleCallBack;
    private static int overTimeTimes = 0;
    private static Runnable loopStatus = new Runnable() {
        @Override
        public void run() {
            loopLockStatus();
        }
    };

    static {
        stringBuilder = new StringBuilder();
    }

    private static final String readStatus = "010300000008440C";
    private static final String closeAll = "01100014000810000000000000000000000000000000002ADA";

    @SuppressLint("HandlerLeak")
    private static Handler mReceiveHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 7) {
                String receive = (String) msg.obj;
                Log.i("锁反馈", receive);
                if (receive.length() == 42) {
//                    String lockStatus = receive.substring(6, 39);
//                    if ( "00010001000100010001000100000000".equals(lockStatus)){
//                        //0001000100010001000100010001000193B4
//                        //关闭监听
//                        stopLoop();
//                        //轮询标签
//                        int which = SPUtil.getInt(SPKey.OPENED_DOOR);
//                        SerialPortProxy.setAntenna(InstructionsUtil.buildSetAntennaOrder(which));
//                    }
                    if (TextUtils.isEmpty(cabinetType)) {
                        cabinetType = SPUtil.getString(SPKey.CABINET_NUM);
                        if (TextUtils.isEmpty(cabinetType)) {
                            Log.e("receive", "柜子类型为空");
                            return;
                        }
                    }
                    int which = SPUtil.getInt(SPKey.OPENED_DOOR);
                    if ("YD".equals(cabinetType.substring(3, 5))) {
                        //8个锁
                        if ("0103100001000100010001000100010001000193B4".equals(receive)) {
                            Log.i("lockReceive", "监听到柜门已关---------------");
                            //关闭监听
                            App.tempLock = SPUtil.getInt(SPKey.OPENED_DOOR);
//                            SPUtil.setInt(SPKey.OPENED_DOOR, 0);
                            stopLoop();
                            //轮询标签
//                            SerialPortProxy.setAntenna(InstructionsUtil.buildSetAntennaOrderMove(which));
//                            SPUtil.setInt(SPKey.OPENED_DOOR,0);
                            if (App.isAdmin) {
                                SerialPortProxy.setAntenna(false, SPUtil.getInt(SPKey.Admin.OPEN_DOOR));
                                EventBus.getDefault().post(new AdminCloseAllDoor());
                            } else {
                                //整柜轮询
                                SerialPortProxy.setAntennaAll();
                                EventBus.getDefault().post(new CloseAllDoor());
                            }
                        }
                    } else {
                        //6个锁
//                        if ("0103100001000100010001000100010000000003B4".equals(receive)
//                                || "010310000100000001000100010001000000000135".equals(receive)) {
//                            //关闭监听
//                            Log.i("lockReceive", "监听到柜门已关---------------");
//                            App.tempLock = SPUtil.getInt(SPKey.OPENED_DOOR);
////                            SPUtil.setInt(SPKey.OPENED_DOOR, 0);
//                            stopLoop();
//                            //轮询标签
//                            SerialPortProxy.setAntenna(InstructionsUtil.buildSetAntennaOrder(which));
//                            EventBus.getDefault().post(new CloseAllDoor());
////                            EventBus.getDefault().post(new AdminCloseAllDoor());
//                        }

                        if ("0103100001000100010001000100010001000193B4".equals(receive)) {
                            Log.i("lockReceive", "监听到柜门已关---------------");
//                            App.tempLock = SPUtil.getInt(SPKey.OPENED_DOOR);
//                            SPUtil.setInt(SPKey.Admin.OPEN_DOOR, -2);
                            stopLoop();
                            //轮询标签
                            if (App.isAdmin) {
                                SerialPortProxy.setAntenna(InstructionsUtil.buildSetAntennaOrder(App.tempLock));
                                Log.d("buildSetAntennaOrder", "-----------轮询柜门--------" + App.tempLock);
                                EventBus.getDefault().post(new AdminCloseAllDoor());
                            } else {
                                Log.i("lockReceive", "监听到柜门已关---------------");
                                App.tempLock = SPUtil.getInt(SPKey.OPENED_DOOR);
//                                SPUtil.setInt(SPKey.OPENED_DOOR, 0);
                                stopLoop();
                                //轮询标签
                                SerialPortProxy.setAntenna(InstructionsUtil.buildSetAntennaOrder(tempWhich));
                                EventBus.getDefault().post(new CloseAllDoor());
                            }

                        }
                    }
//                    if ("0103100001000100010001000100010000000003B4".equals(receive)){
//                        //关闭监听
//                        stopLoop();
//                        //轮询标签
//
//                        if ("YD".equals(cabinetType.substring(3,5))){
//                            SerialPortProxy.setAntenna(InstructionsUtil.buildSetAntennaOrderMove(which));
//                        }else {
//                            SerialPortProxy.setAntenna(InstructionsUtil.buildSetAntennaOrder(which));
//                        }
//                    }
                }
            }
        }
    };
    private static String cabinetType;

    /**
     * 打开串口
     */
    static boolean openDevice(@NonNull SerialPortManager.ReturnHandleCallBack callBack) {
        try {
            mSerialPort = new SerialPort(new File(device), baudrate, 0);
            mInputStream = mSerialPort.getInputStream();
            mOutputStream = mSerialPort.getOutputStream();
            mReturnHandleCallBack = callBack;
            openReceiveThread();
            openSendThread();
            SPUtil.setBoolean(SPKey.hasOpenReceive, true);
            SPUtil.setBoolean(SPKey.hasCloseReceive, true);
            SPUtil.setBoolean(SPKey.getLockStatusReceive, true);
        } catch (IOException | SecurityException e) {
            LogUtil.e("打开串口失败");
            ToastUtil.showCenterToast("打开串口失败");
            e.printStackTrace();
            return false;
        }
        return true;
    }

//    public static boolean which1 = true;
//    public static boolean which2 = true;
//    public static boolean which3 = true;
//    public static boolean which4 = true;
//    public static boolean which5 = true;
//    public static boolean which6 = true;
//    public static boolean which7 = true;
//    public static boolean which8 = true;
//
//    public static void limitTime(final int which){
//        switch (which) {
//            case 1:
//                App.getmHandler().postDelayed(new Runnable() {
//                    @Override
//                    public void run() {
//                        which1 = true;
//                    }
//                },30*1000);
//                break;
//            case 2:
//                App.getmHandler().postDelayed(new Runnable() {
//                    @Override
//                    public void run() {
//                        which2 = true;
//                    }
//                },30*1000);
//                break;
//            case 3:
//                App.getmHandler().postDelayed(new Runnable() {
//                    @Override
//                    public void run() {
//                        which3 = true;
//                    }
//                },30*1000);
//                break;
//            case 4:
//                App.getmHandler().postDelayed(new Runnable() {
//                    @Override
//                    public void run() {
//                        which4 = true;
//                    }
//                },30*1000);
//                break;
//            case 5:
//                App.getmHandler().postDelayed(new Runnable() {
//                    @Override
//                    public void run() {
//                        which5 = true;
//                    }
//                },30*1000);
//                break;
//            case 6:
//                App.getmHandler().postDelayed(new Runnable() {
//                    @Override
//                    public void run() {
//                        which6 = true;
//                    }
//                },30*1000);
//                break;
//            case 7:
//                App.getmHandler().postDelayed(new Runnable() {
//                    @Override
//                    public void run() {
//                        which7 = true;
//                    }
//                },30*1000);
//                break;
//            case 8:
//                App.getmHandler().postDelayed(new Runnable() {
//                    @Override
//                    public void run() {
//                        which8 = true;
//                    }
//                },30*1000);
//                break;
//        }
//
//    }

    static void openLock(int which) {
        Log.i("openLock", "------which------" + which);
        SPUtil.setBoolean(SPKey.hasOpenReceive, false);
        tempWhich = which;
        orderOfLock = InstructionsUtil.openLock(which);
//        orderOfLock = "01100014000810000100010001000100010001000100015D37";
        mReceiveHandler.postDelayed(openLockCallBack, 500);
    }

    static void closeLock() {
        SPUtil.setBoolean(SPKey.hasCloseReceive, false);
        orderOfLock = closeAll;
        mReceiveHandler.postDelayed(closeLockCallBack, 300);
    }

    private static void getLockStatus() {
        SPUtil.setBoolean(SPKey.getLockStatusReceive, false);
        orderOfLock = readStatus;
        mReceiveHandler.postDelayed(readStatusCallBack, 500);
    }

    static void loopLockStatus() {
        orderOfLock = readStatus;
        mReceiveHandler.postDelayed(loopStatus, 1000);
    }

    private static void openSendThread() {
        mSendThread = new Thread() {
            @Override
            public void run() {
                try {
                    while (true) {
                        if (mOutputStream == null) {
                            Log.e("openSendThread", "mOutputStream == null");
                            break;
                        }
                        if (TextUtils.isEmpty(orderOfLock)) {
                            Thread.sleep(50);
                            continue;
                        }
                        byte[] bytes = ByteUtil.hexStr2bytes(orderOfLock);
                        mOutputStream.write(bytes);
                        Log.i("发送成功", orderOfLock);
                        orderOfLock = "";
                    }
                } catch (IOException e) {
                    Log.e("IOException", "-----SendThread------");
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        mSendThread.start();
    }

    //没有校验码生成规则，只能通过返回的操作码和字段长度来判断是什么
    private static void openReceiveThread() {
        mReceiveThread = new Thread() {
            @Override
            public void run() {
                try {
                    while (true) {
                        if (mInputStream == null) {
                            Log.e("openReceiveThread", "mInputStream == null");
                            break;
                        }
                        int available = mInputStream.available();
                        if (available > 0) {
                            byte[] buffer = new byte[available];
                            int read = mInputStream.read(buffer);
                            String hexStr = ByteUtil.bytes2HexStr(buffer);
                            if (hexStr.length() < 4) {
                                stringBuilder.append(hexStr);
                            } else {
                                if (!TextUtils.isEmpty(stringBuilder.toString())) {
                                    //有不完整的数据
                                    stringBuilder.append(hexStr);
                                    hexStr = stringBuilder.toString();
                                }
                                String op = hexStr.substring(2, 4);
                                if ("03".equals(op)) {
                                    //监听锁状态
                                    if (hexStr.length() < 42) {
                                        //不完整的返回
                                        Log.e("不完整的锁监听", hexStr);
                                        if (TextUtils.isEmpty(stringBuilder.toString())) {
                                            stringBuilder.append(hexStr);
                                        }
                                    } else {
                                        Log.d("status", hexStr);
                                        //清除sb
                                        stringBuilder = new StringBuilder();
                                        SPUtil.setBoolean(SPKey.getLockStatusReceive, true);
                                        mReceiveHandler.removeCallbacks(readStatusCallBack);
                                        Message obtain = Message.obtain();
                                        obtain.what = 7;
                                        obtain.obj = hexStr;
                                        mReceiveHandler.sendMessage(obtain);
                                    }
                                } else if ("10".equals(op)) {
                                    //开关锁
                                    if (hexStr.length() < 16) {
                                        //不完整的返回
                                        Log.e("不完整的开关锁", hexStr);
                                        if (TextUtils.isEmpty(stringBuilder.toString())) {
                                            stringBuilder.append(hexStr);
                                        }
                                    } else {
                                        stringBuilder = new StringBuilder();
                                        boolean open = SPUtil.getBoolean(SPKey.hasOpenReceive, true);
                                        boolean close = SPUtil.getBoolean(SPKey.hasCloseReceive, true);
                                        if (!open) {
                                            SPUtil.setBoolean(SPKey.hasOpenReceive, true);
                                            mReceiveHandler.removeCallbacks(openLockCallBack);
                                            Log.i("open", hexStr);
                                            //收到开锁指令，执行关锁指令(断电)
                                            Thread.sleep(100);
                                            closeLock();
                                            //已经有锁打开了
                                            Log.i("---打开成功--", "a-----111-" + tempWhich);

                                            //管理员
                                            if (App.isAdmin)
                                                EventBus.getDefault().post(new AdminOpenSuccess());
                                            else {
                                                String type = SPUtil.getString(SPKey.CABINET_NUM);
                                                if ("DG".equals(type.substring(3, 5)))//固定柜才显示开的那个柜门
                                                    EventBus.getDefault().post(new LockOpenEvent());
                                            }
                                        }
                                        if (!close) {
                                            SPUtil.setBoolean(SPKey.hasCloseReceive, true);
                                            mReceiveHandler.removeCallbacks(closeLockCallBack);
                                            Log.i("---关闭成功--", "a-----111-" + tempWhich);
                                            Log.i("close", hexStr);
                                            Thread.sleep(1000);
                                            loopLockStatus();
                                        }
                                    }
                                } else {
                                    //操作码不是监听锁状态也不是开关锁，丢弃掉此数据
                                    stringBuilder = new StringBuilder();
                                    Log.e("未知的返回格式", hexStr);
                                }
                            }
//                            //有接收到指令
//                            boolean open = SPUtil.getBoolean(SPKey.hasOpenReceive, true);
//                            boolean close = SPUtil.getBoolean(SPKey.hasCloseReceive, true);
//                            boolean status = SPUtil.getBoolean(SPKey.getLockStatusReceive, true);
//                            if (!open) {
//                                SPUtil.setBoolean(SPKey.hasOpenReceive, true);
//                                mReceiveHandler.removeCallbacks(openLockCallBack);
//                                Log.i("open", hexStr);
//                                //收到开锁指令，执行关锁指令
//                                Thread.sleep(200);
//                                closeLock();
//                            }
//                            if (!close) {
//                                SPUtil.setBoolean(SPKey.hasCloseReceive, true);
//                                mReceiveHandler.removeCallbacks(closeLockCallBack);
//                                Log.i("close", hexStr);
//                                getLockStatus();
//                            }
//                            if (!status) {
//                                if (!TextUtils.isEmpty(stringBuilder.toString())) {
//                                    //有不完整的数据
//                                    stringBuilder.append(hexStr);
//                                    hexStr = stringBuilder.toString();
//                                }
//                                if (hexStr.length() < 42) {
//                                    //不完整的返回
//                                    Log.e("不完整的返回", hexStr);
//                                    if (TextUtils.isEmpty(stringBuilder.toString())) {
//                                        stringBuilder.append(hexStr);
//                                    }
//                                } else {
//                                    Log.d("status", hexStr);
//                                    //清除sb
//                                    stringBuilder = new StringBuilder();
//                                    SPUtil.setBoolean(SPKey.getLockStatusReceive, true);
//                                    mReceiveHandler.removeCallbacks(readStatusCallBack);
//                                    Message obtain = Message.obtain();
//                                    obtain.what = 7;
//                                    obtain.obj = hexStr;
//                                    mReceiveHandler.sendMessage(obtain);
//                                }
//                            }
//                            Log.v("qqqqqqqqq","---------");
                            Thread.sleep(50);
                        } else {
                            Thread.sleep(50);
                            Log.v("ReceiveThread无数据", "---LockManager--");
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    Log.e("IOException", "-----ReceiveThread------");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        mReceiveThread.start();
    }


    private static Runnable openLockCallBack = new Runnable() {
        @Override
        public void run() {
            if (!SPUtil.getBoolean(SPKey.hasOpenReceive, false)) {
                if (overTimeTimes < 2) {
                    overTimeTimes++;
                    Log.i("openLockCallBack", "重新发送第" + overTimeTimes + "次");
                    openLock(tempWhich);
                } else {
                    if (mReturnHandleCallBack != null)
                        mReturnHandleCallBack.error(7, NoResponseError);
                    overTimeTimes = 0;
                }
            } else {
                overTimeTimes = 0;
            }
        }
    };
    private static Runnable closeLockCallBack = new Runnable() {
        @Override
        public void run() {
            if (!SPUtil.getBoolean(SPKey.hasCloseReceive, false)) {
                if (overTimeTimes < 2) {
                    overTimeTimes++;
                    Log.i("closeLockCallBack", "重新发送第" + overTimeTimes + "次");
                    closeLock();
                } else {
                    mReturnHandleCallBack.error(8, NoResponseError);
                    overTimeTimes = 0;
                }
            } else {
                overTimeTimes = 0;
            }
        }
    };
    private static Runnable readStatusCallBack = new Runnable() {
        @Override
        public void run() {
            if (!SPUtil.getBoolean(SPKey.getLockStatusReceive, false)) {
                if (overTimeTimes < 2) {
                    overTimeTimes++;
                    Log.i("readStatusCallBack", "重新发送第" + overTimeTimes + "次");
                     getLockStatus();
                } else {
                    mReturnHandleCallBack.error(9, NoResponseError);
                    overTimeTimes = 0;
                }
            } else {
                overTimeTimes = 0;
            }
        }
    };

    static void stopLoop() {
        mReceiveHandler.removeCallbacks(loopStatus);
    }


    static void closeSerialPort() {
        if (mSerialPort != null) {
            mSerialPort.close();
        }
        if (mInputStream != null) {
            try {
                mInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        if (mOutputStream != null) {
            try {
                mOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
